

using System;
using TripleA.Core.Database;
using TripleA.Core.Interfaces;
using TripleA.Core.Interfaces.Entities;

namespace TripleA.Core.Extensions.Database
{
    public static class DatabaseExtensions
    {
        /// <summary>
        /// Variation that expects connection string to be stored in app.config
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="config"></param>
        /// <param name="statement"></param>
        /// <param name="expectedRows"></param>
        /// <returns></returns>
        public static IPipelineConfig<T> RunSqlCommand<T>(this IPipelineConfig<T> config, 
            ISqlStatement statement,
            int expectedRows)
            where T: Context
        {
            return RunSqlCommand(config, null, statement, expectedRows);
        }

        /// <summary>
        /// Variation that expects connection string to be stored in app.config
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="config"></param>
        /// <param name="statement"></param>
        /// <param name="expectedRows"></param>
        /// <returns></returns>
        public static IPipelineConfig<T> RunSqlCommand<T>(this IPipelineConfig<T> config, 
            ISqlStatement statement,
            Predicate<int> expectedRows)
            where T: Context
        {
            return RunSqlCommand(config, null, statement, expectedRows);
        }

        public static IPipelineConfig<T> RunSqlCommand<T>(this IPipelineConfig<T> config, 
            string connectionName,
            ISqlStatement statement,
            int expectedRows)
            where T: Context
        {
            config.RunStep(new SqlServerCommandStep<T>
                               {
                                   ConnectionName = connectionName,
                                   ExpectedRows = expectedRows,
                                   Statement = statement
                               });
            return config;  
        }

        public static IPipelineConfig<T> RunSqlCommand<T>(this IPipelineConfig<T> config, 
            string connectionName,
            ISqlStatement statement,
            Predicate<int> expectedRows)
            where T: Context
        {
            config.RunStep(new SqlServerCommandStep<T>
                               {
                                   ConnectionName = connectionName,
                                   ExpectedRowsTest = expectedRows,
                                   Statement = statement
                               });
            return config;  
        }

        /// <summary>
        /// Variation that expects connection string to be stored in app.config
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="config"></param>
        /// <param name="statement"></param>
        /// <param name="expectedRows"></param>
        /// <returns></returns>
        public static IPipelineConfig<T> RunSqlQuery<T>(this IPipelineConfig<T> config, 
            ISqlStatement statement,
            int expectedRows)
            where T: Context
        {
            return RunSqlQuery(config, null, statement, expectedRows);
        }

        /// <summary>
        /// Variation that expects connection string to be stored in app.config
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="config"></param>
        /// <param name="statement"></param>
        /// <param name="expectedRows"></param>
        /// <returns></returns>
        public static IPipelineConfig<T> RunSqlQuery<T>(this IPipelineConfig<T> config, 
            ISqlStatement statement,
            Predicate<int> expectedRows)
            where T: Context
        {
            return RunSqlQuery(config, null, statement, expectedRows);
        }

        public static IPipelineConfig<T> RunSqlQuery<T>(this IPipelineConfig<T> config, 
            string connectionName,
            ISqlStatement statement,
            int expectedRows)
            where T: Context
        {
            config.RunStep(new SqlServerQueryStep<T>
                               {
                                   ConnectionName = connectionName,
                                   ExpectedRows = expectedRows,
                                   Statement = statement
                               });
            return config;  
        }

        public static IPipelineConfig<T> RunSqlQuery<T>(this IPipelineConfig<T> config, 
            string connectionName,
            ISqlStatement statement,
            Predicate<int> expectedRows)
            where T: Context
        {
            config.RunStep(new SqlServerQueryStep<T>
                               {
                                   ConnectionName = connectionName,
                                   ExpectedRowsTest = expectedRows,
                                   Statement = statement
                               });
            return config;  
        }

        /// <summary>
        /// Variation that expects connection string to be stored in app.config
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="config"></param>
        /// <param name="database"></param>
        /// <param name="username"></param>
        /// <param name="roles"></param>
        /// <returns></returns>
        public static IPipelineConfig<T> UserIsInSqlServerDatabaseRole<T>(this IPipelineConfig<T> config,
            string database,
            string username, 
            params string[] roles)
            where T : Context
        {
            return UserIsInSqlServerDatabaseRole(config, null, database, username, roles);
        }


        public static IPipelineConfig<T> UserIsInSqlServerDatabaseRole<T>(this IPipelineConfig<T> config,
            string connectionName,
            string database,
            string username, 
            params string[] roles)
            where T : Context
        {
            config.RunStep(new SqlServer2008AssertRolesStep<T>
                               {
                                   ConnectionName = connectionName,
                                   Database = database,
                                   Roles = roles,
                                   Username = username
                               });
            return config;
        }

        /// <summary>
        /// Variation that expects connection string to be stored in app.config
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="config"></param>
        /// <param name="username"></param>
        /// <returns></returns>
        public static IPipelineConfig<T> SqlServerHasLogin<T>(this IPipelineConfig<T> config,
            string username)
            where T : Context
        {
            return SqlServerHasLogin(config, null, username);
        }

        public static IPipelineConfig<T> SqlServerHasLogin<T>(this IPipelineConfig<T> config,
            string connectionName,
            string username)
            where T : Context
        {
            config.RunStep(new SqlServer2008AssertLoginStep<T>
                               {
                                   ConnectionName = connectionName,
                                   Username = username
                               });
            return config;
        }

        /// <summary>
        /// Variation that expects connection string to be stored in app.config
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="config"></param>
        /// <param name="username"></param>
        /// <returns></returns>
        public static IPipelineConfig<T> SqlServerDatabaseHasUser<T>(this IPipelineConfig<T> config,
            string username)
            where T : Context
        {
            return SqlServerDatabaseHasUser(config, null, username);
        }

        public static IPipelineConfig<T> SqlServerDatabaseHasUser<T>(this IPipelineConfig<T> config,
            string connectionName,
            string username)
            where T : Context
        {
            config.RunStep(new SqlServer2008AssertUserStep<T>
                               {
                                   ConnectionName = connectionName,
                                   Username = username
                               });
            return config;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="config"></param>
        /// <param name="server"></param>
        /// <param name="scriptFilename"></param>
        /// <param name="sqlcmdPath"></param>
        /// <param name="username"></param>
        /// <param name="password"></param>
        /// <param name="otherArgs"></param>
        /// <returns></returns>
        public static IPipelineConfig<T> RunSqlScriptExplicitSqlCmdPath<T>(this IPipelineConfig<T> config,
            string server,
            string scriptFilename,
            string sqlcmdPath,
            string username = null,
            string password = null,
            string otherArgs = null
            )
            where T : Context
        {
            config.RunStep(new SqlServer2008RunScript<T>
                               {
                                   Server = server,
                                   ExeFilePath = sqlcmdPath,
                                   ScriptFilename = scriptFilename,
                                   Username = username,
                                   Password = password,
                                   OtherArgs = otherArgs
                               });
            return config;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="config"></param>
        /// <param name="server"></param>
        /// <param name="scriptFilename"></param>
        /// <param name="username"></param>
        /// <param name="password"></param>
        /// <param name="otherArgs"></param>
        /// <returns></returns>
        public static IPipelineConfig<T> RunSqlScript<T>(this IPipelineConfig<T> config,
            string server,
            string scriptFilename,
            string username = null,
            string password = null,
            string otherArgs = null
            )
            where T : Context
        {
            return RunSqlScriptExplicitSqlCmdPath(config, server, scriptFilename, null, username, password, otherArgs);
        }
    }
}